package cn.silver.module.web.service;

import cn.hutool.captcha.AbstractCaptcha;
import cn.hutool.captcha.generator.CodeGenerator;
import cn.hutool.core.util.IdUtil;
import cn.silver.framework.core.constant.Constants;
import cn.silver.framework.core.constant.GlobalConstants;
import cn.silver.framework.core.utils.SpringUtils;
import cn.silver.framework.core.utils.StringUtils;
import cn.silver.framework.core.utils.reflect.ReflectUtils;
import cn.silver.framework.redis.utils.RedisUtils;
import cn.silver.framework.web.enums.CaptchaTypeEnums;
import cn.silver.framework.web.properties.CaptchaProperties;
import cn.silver.module.web.model.CaptchaModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Service;

import java.time.Duration;

/**
 * @author zhouxiaobo
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysCaptchaService {

    private final CaptchaProperties captchaProperties;

    public CaptchaModel generateCaptcha(CaptchaTypeEnums captchaTypeEnums) {
        CaptchaModel captchaModel = new CaptchaModel();
        // 保存验证码信息
        String uuid = IdUtil.simpleUUID();
        // 生成验证码
        Integer length = captchaTypeEnums.getLength();
        CodeGenerator codeGenerator = ReflectUtils.newInstance(captchaTypeEnums.getClazz(), length);
        AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz());
        captcha.setGenerator(codeGenerator);
        captcha.createCode();
        String code = captcha.getCode();
        if (CaptchaTypeEnums.MATH.getCode().equals(captcha.getCode())) {
            ExpressionParser parser = new SpelExpressionParser();
            Expression exp = parser.parseExpression(StringUtils.remove(code, "="));
            code = exp.getValue(String.class);
        }
        RedisUtils.setCacheObject(GlobalConstants.CAPTCHA_CODE_KEY, uuid, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
        captchaModel.setUuid(uuid);
        captchaModel.setImg(captcha.getImageBase64());
        return captchaModel;
    }
}
